package com.amado.course35Concurrent;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
 * 使用线程池的好处
1.通过重复利用已创建的线程， 减少在创建和销毁线程上所花的时间以及系统资源的开销。
2.提高响应速度。 当任务到达时， 任务可以不需要等到线程创建就可以立即行。
3.提高线程的可管理性。 使用线程池可以对线程进行统一的分配和监控。
4.如果不使用线程池， 有可能造成系统创建大量线程而导致消耗完系统内存。

虽然线程池是构建多线程应用程序的强大机制， 但使用它并不是没有风险的。
（1） 线程池的大小。 多线程应用并非线程越多越好， 需要根据系统运行的软硬件环境以及应用本身的特点决定线程池的大小。
 一般来说， 如果代码结构合理的话， 线程数目与 CPU数量相适合即可。 如果线程运行时可能出现阻塞现象， 
 可相应增加池的大小； 如有必要可采用自适应算法来动态调整线程池的大小， 以提高 CPU 的有效利用率和系统的整体性能。
（2） 并发错误。 多线程应用要特别注意并发错误， 要从逻辑上保证程序的正确性， 注意避免死锁现象的发生。
（3） 线程泄漏。 这是线程池应用中一个严重的问题， 当任务执行完毕而线程没能返回池中就会发生线程泄漏现象。
 *
 */
public class S12Executorstest {
	public static void main(String[] args) {
//		 newCachedThreadPool();
		 newFixedThreadPool();
//		newSingleThreadScheduledExecutor();
//		 newScheduledThreadPool();
	}

	public static void newCachedThreadPool() {
		// 线程池里面的线程数会动态变化，并可在线程线被移除前重用,最大的线程数==Integer.MAX_VALUE
		ExecutorService threadPool = Executors.newCachedThreadPool();
		for (int i = 1; i <= 100; i++) {
			final int task = i; // 10个任务
			try {
				Thread.sleep(1);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			threadPool.execute(new Runnable() { // 接受一个Runnable实例
				public void run() {
					try {
						Thread.sleep(300);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					System.out.println("线程名字： " + Thread.currentThread().getName() + "  任务名为： " + task);
				}
			});
		}
	}

	public static void newFixedThreadPool() {
		// 创建一个可重用固定线程数的线程池，以共享的无界队列方式来运行这些线程。
		ExecutorService threadPool = Executors.newFixedThreadPool(3);
		for (int i = 1; i <= 100; i++) {
			final int task = i; // 10个任务

			threadPool.execute(new Runnable() { // 接受一个Runnable实例
				public void run() {
					try {
						Thread.sleep(400);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					System.out.println("线程名字： " + Thread.currentThread().getName() + "  任务名为： " + task);
				}
			});
		}
		System.out.println("finins");
	}

	public static void newSingleThreadScheduledExecutor() {
		// 创建一个单线程执行程序，它可安排在给定延迟后运行命令或者定期地执行。
		ScheduledExecutorService threadPool = Executors.newSingleThreadScheduledExecutor();
		for (int i = 1; i <= 100; i++) {
			final int task = i; // 10个任务
//			threadPool.schedule(new Runnable() { // 接受一个Runnable实例
//				public void run() {
//					System.out.println("线程名字： " + Thread.currentThread().getName() + "  任务名为： " + task);
//				}
//			}, 1, TimeUnit.NANOSECONDS);
			// 接受一个Runnable实例
			threadPool.execute(new Runnable() { 
				public void run() {
					System.out.println("线程名字： " + Thread.currentThread().getName() + "  任务名为： " + task);
					try {
						Thread.sleep(300);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			});
		}
	}

	public static void newScheduledThreadPool() {
		// 创建一个线程池，它可安排在给定延迟后运行命令或者定期地执行。
		ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(5);
		for (int i = 1; i <= 100; i++) {
			final int task = i; // 10个任务
//			threadPool.execute(new Runnable() { // 接受一个Runnable实例
//				public void run() {
//					System.out.println("线程名字： " + Thread.currentThread().getName() + "  任务名为： " + task);
//				}
//			});
			threadPool.schedule(new Runnable() { // 接受一个Runnable实例
				public void run() {
					System.out.println("线程名字： " + Thread.currentThread().getName() + "  任务名为： " + task);
				}
			}, 1, TimeUnit.SECONDS);
//			threadPool.execute(new Runnable() { // 接受一个Runnable实例
//				public void run() {
//					System.out.println("线程名字： " + Thread.currentThread().getName() + "  任务名为： " + task);
//				}
//			});
		}
	}
}
